namespace Bootsy.Jira

import Bootsy.Jira.RPC
import Bootsy.Core
import Bootsy.PEG
import System.Collections.Generic

class JiraBot(GrammarBasedBot):
	_jira as IJiraService
	
	def constructor([required] jira as IJiraService):
		super(SetUpGrammar())
		_jira = jira
		
	def SetUpGrammar():
		searchRule = literal("search") >> remaining(ProcessSearch)
		topRule = literal("top") >> integer(ProcessTop)
		issueRule = re(/^[A-Za-z]{3}-\d+/, ProcessIssue)
		idsRule = literal("ids", ProcessIds)
		return literal("!jira") >> (searchRule | topRule | issueRule | idsRule) >> eof()
		
	def ProcessSearch(text as string, message as IChatMessage):
		found = _jira.SearchIssues(text)
		if len(found) == 0:
			message.Chat.PostMessage("Sorry, no matches for '${text}'.")
		else:
			message.Chat.PostMessage(FormatIssues(found))
		
	def ProcessTop(count as int, message as IChatMessage):
		message.Chat.PostMessage(FormatIssues(_jira.GetTop(count)))
		
	def ProcessIssue(ticket as string, message as IChatMessage):
		message.Chat.PostMessage(GetTicketString(ticket))
		
	def ProcessIds(literal as string, message as IChatMessage):
		try:
			message.Chat.PostMessage(QueryIds())
		except x:
			message.Chat.PostMessage(x.ToString())
		
	def QueryIds():
		statuses = ("1" /*Open*/, "3" /*In Progress*/)
		issues = issue for issue in _jira.GetProgressReport() if issue.status in statuses
		issuesByDev = GroupByDev(issues)
		
		reply = System.IO.StringWriter()
		for key in Boo.Lang.List(issuesByDev.Keys).Sort():
			reply.WriteLine("${key}: ${issuesByDev[key]} IDS")
		reply.WriteLine("Total: ${TotalIds(issues)} IDS")
		return reply.ToString()
		
	def TotalIds(issues as IEnumerable of RemoteIssue):
		total = 0
		for issue in issues:
			total += Ids(issue)
		return total
		
	def GroupByDev(issues as IEnumerable of RemoteIssue):
		result = {}
		addIds = do (key, value as single):
			if key is null: return
			result[key] = value + cast(single, result[key] or 0.0)
			
		for issue in issues:
			ids = Ids(issue)			
			addIds(issue.assignee, ids)
			peers = Peers(issue)
			continue if peers is null
			for peer in peers:
				addIds(peer, ids) 
	
		return result
		
	def Peers(issue as RemoteIssue):
		return CustomFieldValues(issue, "customfield_10000")
			
	def Ids(issue as RemoteIssue):
		return single.Parse(CustomFieldValues(issue, "customfield_10040")[0])
		
	def CustomFieldValues(issue as RemoteIssue, customFieldId as string):
		for customField in issue.customFieldValues:
			if customField.customfieldId == customFieldId:
				return customField.values
			
	def GetTicketString(ticket as string):
		issue = _jira.GetIssue(ticket)
		return FormatIssue(issue)
		
	def FormatIssues(issues):
		return join(FormatIssue(issue) for issue in issues, "\n")
			
	def FormatIssue(issue as RemoteIssue):
		return "${issue.key} - ${_jira.GetResolutionName(issue.resolution)} - ${issue.summary}"
